package com.shm.leetcode;

/**
 * 509. 斐波那契数
 * 斐波那契数，通常用 F(n) 表示，形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始，后面的每一项数字都是前面两项数字的和。也就是：
 *
 * F(0) = 0，F(1) = 1
 * F(n) = F(n - 1) + F(n - 2)，其中 n > 1
 * 给你 n ，请计算 F(n) 。
 *
 *
 *
 * 示例 1：
 *
 * 输入：2
 * 输出：1
 * 解释：F(2) = F(1) + F(0) = 1 + 0 = 1
 * 示例 2：
 *
 * 输入：3
 * 输出：2
 * 解释：F(3) = F(2) + F(1) = 1 + 1 = 2
 * 示例 3：
 *
 * 输入：4
 * 输出：3
 * 解释：F(4) = F(3) + F(2) = 2 + 1 = 3
 *
 *
 * 提示：
 *
 * 0 <= n <= 30
 * @author SHM
 */
public class Fib {
    public int fib(int n) {
        if(n==0){
            return 0;
        }
        if(n==1){
            return 1;
        }
        return fib(n-1)+fib(n-2);
    }

    /**
     * 方法一：动态规划
     * 斐波那契数的边界条件是 F(0)=0F(0)=0 和 F(1)=1F(1)=1。当 n>1n>1 时，每一项的和都等于前两项的和，因此有如下递推关系：
     *
     * F(n)=F(n-1)+F(n-2)
     * F(n)=F(n−1)+F(n−2)
     *
     * 由于斐波那契数存在递推关系，因此可以使用动态规划求解。动态规划的状态转移方程即为上述递推关系，边界条件为 F(0)F(0) 和 F(1)F(1)。
     *
     * 根据状态转移方程和边界条件，可以得到时间复杂度和空间复杂度都是 O(n)O(n) 的实现。由于 F(n)F(n) 只和 F(n-1)F(n−1) 与 F(n-2)F(n−2) 有关，因此可以使用「滚动数组思想」把空间复杂度优化成 O(1)O(1)。如下的代码中给出的就是这种实现。
     *
     * 复杂度分析
     *
     * 时间复杂度：O(n)O(n)。
     *
     * 空间复杂度：O(1)O(1)。
     * 作者：LeetCode-Solution
     * 链接：https://leetcode-cn.com/problems/fibonacci-number/solution/fei-bo-na-qi-shu-by-leetcode-solution-o4ze/
     * @param n
     * @return
     */
    public int fib_2(int n) {
        if(n<2){
            return n;
        }
        int p=0,q=0,r=1;
        for (int i = 2; i <= n; i++) {
            p=q;
            q=r;
            r=p+q;
        }
        return r;
    }
}
